//
// Created by lz on 2021/2/17.
//

#ifndef MYWEBLIB_NET_EVENTLOOP_H_
#define MYWEBLIB_NET_EVENTLOOP_H_

#include <atomic>
#include <functional>
#include <vector>

#include <boost/any.hpp>

#include "base/Mutex.h"
#include "base/CurrentThread.h"
#include "base/Timestamp.h"
#include "net/Callbacks.h"
#include "net/TimerId.h"

namespace lzweb {
namespace net {

class Channel;
class Poller;
class TimerQueue;
///
/// Reactor, at most one per thread.
///
/// This is an interface class, so don't expose too much details.

class EventLoop : noncopyable {
public:
  using Functor = std::function<void()>;

  EventLoop();
  ~EventLoop();  // force out-line dtor, for std::unique_ptr members.

  ///
  /// Loops forever.
  ///
  /// Must be called in the same thread as creation of the object.
  ///
  void loop();

  /// Quits loop.
  ///
  /// This is not 100% thread safe, if you call through a raw pointer,
  /// better to call through shared_ptr<EventLoop> for 100% safety.
  void quit();

  ///
  /// Time when poll returns, usually means data arrival.
  ///
  TimeStamp pollReturnTime() const { return pollReturnTime_; }

  int64_t iteration() const { return iteration_; }

  /// Runs callback immediately in the loop thread.
  /// It wakes up the loop, and run the cb.
  /// If in the same loop thread, cb is run within the function.
  /// Safe to call from other threads.
  void runInLoop(Functor cb);
  /// Queues callback in the loop thread.
  /// Runs after finish pooling.
  /// Safe to call from other threads.
  void queueInLoop(Functor cb);

  size_t queueSize() const;

  // timers

  ///
  /// Runs callback at 'time'.
  /// Safe to call from other threads.
  ///
  TimerId runAt(TimeStamp time, TimerCallback cb);
  ///
  /// Runs callback after @c delay seconds.
  /// Safe to call from other threads.
  ///
  TimerId runAfter(double delay, TimerCallback cb);
  ///
  /// Runs callback every @c interval seconds.
  /// Safe to call from other threads.
  ///
  TimerId runEvery(double interval, TimerCallback cb);
  ///
  /// Cancels the timer.
  /// Safe to call from other threads.
  ///
  void cancel(TimerId timerId);

  // internal usage
  void wakeup();
  void updateChannel(Channel *channel);
  void removeChannel(Channel *channel);
  bool hasChannel(Channel *channel);

  // pid_t threadId() const { return threadId_; }

  void assertInLoopThread() {
	if (!isInLoopThread()) {
	  abortNotInLoopThread();
	}
  }

  bool isInLoopThread() const { return threadId_ == CurrentThread::tid(); }
  // bool callingPendingFunctors() const { return callingPendingFunctors_; }
  bool eventHandling() const { return eventHandling_; }

  void setContext(const boost::any &context) { context_ = context; }

  const boost::any &getContext() const {
	return context_;
  }

  boost::any* getMutableContext()
  {return &context_; }

  static EventLoop* getEventLoopOfCurrentThread();


private:

  void abortNotInLoopThread();
  void handleRead();     //waked up
  void doPendingFunctors();

  void printActiveChannels() const; // DEBUG

  using ChannelList = std::vector<Channel *>;

  bool looping_;    /* atomic */
  std::atomic<bool> quit_;
  bool eventHandling_;    /* atomic */
  bool callingPendingFunctors_;    /* atomic */
  int64_t iteration_;
  const pid_t threadId_;
  TimeStamp pollReturnTime_;    // poll()函数返回值，返回poll_wait触发时的时间点
  std::unique_ptr<Poller> poller_;
  std::unique_ptr<TimerQueue> timerQueue_;
  int wakeupFd_;    // eventfd(),一个 事件对象 (eventfd object), 用来实现进程(线程)间的等待/通知(wait/notify) 机制.

  // unlike in TimerQueue, which is an internal class,
  // we don't expose Channel to client.

  std::unique_ptr<Channel> wakeupChannel_;
  boost::any context_;

  // scratch variables   scratch -> 抓，刮；凑合的
  ChannelList activeChannels_;
  Channel *currentActiveChannel_;

  mutable MutexLock mutex_;
  std::vector<Functor> pendingFunctors_ GUARDED_BY(mutex_);

};

}
}// namespace lzweb


#endif //MYWEBLIB_NET_EVENTLOOP_H_
